package com.zhiyou.app.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhiyou.app.common.constant.EncryptedTool;
import com.zhiyou.app.common.constant.UserHandler;
import com.zhiyou.app.common.exception.BizException;
import com.zhiyou.app.common.util.SecCheckUtil;
import com.zhiyou.app.common.vo.resp.BizResponseCode;
import com.zhiyou.app.config.oss.OssUtil;
import com.zhiyou.app.mapper.UserMapper;
import com.zhiyou.app.pojo.bo.SecCheckResult;
import com.zhiyou.app.pojo.entity.UserEntity;
import com.zhiyou.app.pojo.entity.UserWalletEntity;
import com.zhiyou.app.pojo.enums.DeviceTypeEnum;
import com.zhiyou.app.pojo.enums.UserStatusEnum;
import com.zhiyou.app.pojo.enums.UserTypeEnum;
import com.zhiyou.app.pojo.vo.ImproveUserProfileVo;
import com.zhiyou.app.pojo.vo.UserInfoVo;
import com.zhiyou.app.pojo.vo.UserLoginRequestVo;
import com.zhiyou.app.pojo.vo.UserLoginResponseVo;
import com.zhiyou.app.service.IUserService;
import com.zhiyou.app.service.IUserWalletService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author jonathan.z
 * @since 2025-07-03
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements IUserService {
    @Resource
    private WxMaService wxMaService;

    @Resource
    private EncryptedTool encryptedTool;

    @Resource
    private IUserWalletService userWalletService;
    @Resource
    private OssUtil ossUtil;
    @Resource
    private SecCheckUtil secCheckUtil;

    @Transactional
    @Override
    public UserLoginResponseVo userLogin(UserLoginRequestVo userLoginRequestVo) {
        if (StrUtil.isNotEmpty(userLoginRequestVo.getLoginCode()) && userLoginRequestVo.getDeviceType() == DeviceTypeEnum.miniapp) {
            WxMaJscode2SessionResult sessionInfo;
            try {
                sessionInfo = wxMaService.getUserService().getSessionInfo(userLoginRequestVo.getLoginCode());
            } catch (WxErrorException e) {
                log.error("微信登录失败", e);
                throw new BizException(BizResponseCode.AUTH_ERROR);
            }
            UserLoginResponseVo userLoginVo = new UserLoginResponseVo().setSi(encryptedTool.encode(sessionInfo.getSessionKey()));
            String openId = sessionInfo.getOpenid();
            UserEntity one = getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getOpenId, openId));
            if (one == null) {
                one = createUser(userLoginRequestVo.getInvitationCode(), sessionInfo);
                userLoginVo.setNewCreated(true);
            } else if (one.getStatus() == UserStatusEnum.NORMAL) {
                one.setLastestLoginTime(new Date());
                updateById(one);
            } else {
                throw new BizException("用户已经【" + one.getStatus().getName() + "】,请联系管理员");
            }
            userLoginVo.setUserInfo(covertUserInfoVo(one));
            // 登录
            UserHandler.userLogin(userLoginRequestVo.getDeviceType(), UserTypeEnum.mini, one.getId());
            return userLoginVo.setToken(StpUtil.getTokenValue());
        } else if (StrUtil.isNotEmpty(userLoginRequestVo.getUsername()) && StrUtil.isNotEmpty(userLoginRequestVo.getPassword())) {
            if(userLoginRequestVo.getUsername().equals("admin") && userLoginRequestVo.getPassword().equals("zhiyou2025!")){
                // 登录
                UserHandler.userLogin(userLoginRequestVo.getDeviceType(), UserTypeEnum.staff, 0);
                UserLoginResponseVo userLoginVo = new UserLoginResponseVo();
                return userLoginVo.setToken(StpUtil.getTokenValue());
            }
        }
        return null;
    }

    @Override
    public UserInfoVo improveUserProfile(ImproveUserProfileVo improveUserProfileVo) {
        Integer userId = UserHandler.getLoginUser().getUserId();
        UserEntity userEntity = getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getId, userId));
        if (improveUserProfileVo.getNickname() != null) {
            userEntity.setNickname(improveUserProfileVo.getNickname());
        }
        if (improveUserProfileVo.getPhoto() != null) {
            userEntity.setPhoto(improveUserProfileVo.getPhoto());
        }
        updateById(userEntity);
        return covertUserInfoVo(userEntity);
    }

    @Override
    public UserInfoVo bindPhone(String code) {
        try {
            Integer userId = UserHandler.getLoginUser().getUserId();
            WxMaPhoneNumberInfo phoneNumber = wxMaService.getUserService().getPhoneNumber(code);
            update(new LambdaUpdateWrapper<UserEntity>().eq(UserEntity::getId, userId).set(UserEntity::getPhone, phoneNumber.getPhoneNumber()));
            return covertUserInfoVo(getById(userId));
        } catch (WxErrorException e) {
            log.error("绑定电话号码失败", e);
            throw new BizException("绑定电话号码失败");
        }
    }

    @Override
    public String uploadPhoto(MultipartFile photo) {
        String substring = Objects.requireNonNull(photo.getOriginalFilename()).substring(photo.getOriginalFilename().lastIndexOf("."));
        try {
            Integer userId = UserHandler.getLoginUser().getUserId();
            String url = ossUtil.uploadAndUseFile("photo_" + userId + substring, "photo", photo.getInputStream());
            SecCheckResult secCheckResult = secCheckUtil.waitForSecCheckResult(60, url, null).get();
            if (!secCheckResult.isPassed()) {
                log.info("文件违规:{}，删除文件：{},结果：{}", secCheckResult.getErrMsg(), url, ossUtil.deleteFile(url));
                throw new BizException("图片内容违规");
            } else {
                log.info("头像图片内容合规:{}", url);
            }
            update(new LambdaUpdateWrapper<UserEntity>().set(UserEntity::getPhoto, url).eq(UserEntity::getId, userId));
            return url;
        } catch (BizException e) {
            throw e;
        }catch (Exception e) {
            log.error("上传图片失败", e);
            throw new BizException("上传图片失败");
        }
    }

    @Override
    public UserInfoVo getProfile(Integer userId) {
        if (userId == null) {
            Object userIdStr = StpUtil.getTokenInfo().getLoginId();
            if (userIdStr instanceof String) {
                userId = Integer.valueOf((String) userIdStr);
            } else {
                userId = (Integer) userIdStr;
            }
        }
        if (userId != null) {
            UserEntity userEntity = getById(userId);
            UserInfoVo userInfoVo = covertUserInfoVo(userEntity);
            getInvitationUser(userEntity.getInvitationId(), userInfoVo);
            return userInfoVo;
        }
        return null;
    }


    private UserInfoVo covertUserInfoVo(UserEntity userEntity) {
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtil.copyProperties(userEntity, userInfoVo);
        userInfoVo.setUserId(userEntity.getId());
        getInvitationUser(userEntity.getInvitationId(), userInfoVo);
        return userInfoVo;
    }

    /**
     * 获取邀请用户
     *
     * @param userId     用户ID
     * @param userInfoVo 用户信息
     */
    private void getInvitationUser(Integer userId, UserInfoVo userInfoVo) {
        if (userId == null || userId == 0) {
            return;
        }
        UserEntity userEntity = getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getId, userId));
        if (userEntity == null) {
            throw new BizException(BizResponseCode.INVITATION_CODE_ERROR);
        } else {
            userInfoVo.setInvitationInfo(userEntity.getNickname() + "(" + userEntity.getInvitationId() + ")");
        }
    }

    /**
     * 创建用户
     *
     * @param invitationCode 邀请码
     * @param sessionInfo    session
     * @return 用户
     */
    private UserEntity createUser(String invitationCode, WxMaJscode2SessionResult sessionInfo) {
        Integer invitationId = null;
        if (invitationCode != null) {
            invitationId = parseInvitationCode(invitationCode);
        }
        UserEntity userEntity = new UserEntity()
                .setInvitationId(invitationId)
                .setStatus(UserStatusEnum.NORMAL)
                .setWechatId(sessionInfo.getUnionid()).setOpenId(sessionInfo.getOpenid()).setLastestLoginTime(new Date());
        save(userEntity);
        userWalletService.save(new UserWalletEntity().setUserId(userEntity.getId()));
        return userEntity;
    }

    @Override
    public String createInvitationCode() {
        return generateInvitationCode();
    }

    private String generateInvitationCode() {
        return encryptedTool.encode(String.valueOf(System.currentTimeMillis()).substring(0, 10) + UserHandler.getLoginUser().getUserId() + RandomUtil.randomString(10));
    }

    private Integer parseInvitationCode(String invitationCode) {
        String decode = encryptedTool.decode(invitationCode);
        String substring = decode.substring(10);
        try {
            return Integer.parseInt(substring.substring(0, substring.length() - 10));
        } catch (NumberFormatException e) {
            log.error("解析邀请人报错", e);
            throw new BizException(BizResponseCode.INVITATION_CODE_ERROR);
        }
    }
}
